/*
 * Copyright 2023-2025 Dozingfiretruck
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef __NES_H__
#define __NES_H__


#include "nes_default.h"
#include "nes_log.h"
#include "nes_rom.h"
#include "nes_cpu.h"
#include "nes_ppu.h"
#include "nes_apu.h"
#include "nes_mapper.h"

#ifdef __cplusplus
    extern "C" {
#endif

#define NES_VERSION_MAJOR       0
#define NES_VERSION_MINOR       0
#define NES_VERSION_PATCH       1

#define STRINGIFY_HELPER(x)     #x
#define NES_VERSION_STRING      STRINGIFY_HELPER(NES_VERSION_MAJOR) "." STRINGIFY_HELPER(NES_VERSION_MINOR) "." STRINGIFY_HELPER(NES_VERSION_PATCH)

#define NES_NAME                "NES"

#define NES_URL                 "https://github.com/Dozingfiretruck/nes"

#define NES_WIDTH               256
#define NES_HEIGHT              240

// https://www.nesdev.org/wiki/Cycle_reference_chart
#define NES_CPU_CLOCK_FREQ      (1789773) // 21.47~ MHz ÷ 12 = 1.789773 MHz

// https://www.nesdev.org/w/images/default/4/4f/Ppu.svg
#define NES_PPU_CPU_CLOCKS		(113)     // 341 × 4 ÷ 12 = 113 2⁄3

#define NES_OK                  (0) 
#define NES_ERROR               (-1)

/* 
 * nes_t 结构体优化：按照4字节对齐以优化ARM Cortex-M3的内存访问效率
 * 字段顺序按照访问频率和大小进行排列，减少padding，确保4字节对齐
 */
typedef struct nes{
    /* 最常用的控制字段：放在结构体最前面，确保4字节对齐 */
    uint16_t scanline;                    /*  扫描线编号，访问频率极高，2字节，与后续字段组合4字节对齐 */
    uint8_t nes_quit;                     /*  退出标志，访问频率高，1字节 */
#if (NES_FRAME_SKIP != 0)
    uint8_t nes_frame_skip_count;         /*  跳帧计数，1字节 */
    uint8_t _padding1[2];                /*  填充字节，确保后续指针4字节对齐 */
#else
    uint8_t _padding1[1];                 /*  填充字节，确保后续指针4字节对齐 */
#endif
    /*  指针字段：4字节对齐，放在一起 */
    nes_color_t nes_draw_data[NES_WIDTH*NES_HEIGHT]/**nes_draw_data*/;           /*  绘制数据指针，访问频率高，4字节对齐 */
    /*  CPU和PPU结构体：访问频率极高，放在前面 */
    nes_cpu_t nes_cpu;                    /*  CPU状态，访问频率极高，已优化对齐 */
    nes_ppu_t nes_ppu;                    /*  PPU状态，访问频率高，包含大数组 */
#if (NES_ENABLE_SOUND==1)
    nes_apu_t nes_apu;                    /*  APU状态，访问频率中等，包含大数组 */
#endif
    /*  ROM信息和Mapper：访问频率较低，放在后面 */
    nes_rom_info_t nes_rom;               /*  ROM信息，访问频率较低，已优化对齐 */
    nes_mapper_t nes_mapper;              /*  Mapper回调函数表，访问频率中等，已优化对齐 */
} __attribute__((aligned(4))) nes_t;      /*  显式指定4字节对齐 */


//struct nes;
//typedef struct nes nes_t;

nes_t* nes_init(void);
int nes_deinit(nes_t *nes);

void nes_run(nes_t* nes);

#if (NES_USE_FS == 1)
int nes_load_file(nes_t* nes, const char* file_path);
int nes_unload_file(nes_t* nes);
#endif

int nes_load_rom(nes_t* nes, const uint8_t* nes_rom);
int nes_unload_rom(nes_t* nes);

int nes_initex(nes_t* nes);
int nes_deinitex(nes_t* nes);
void nes_frame(nes_t* nes);

#ifdef __cplusplus          
    }
#endif

#endif
